import {APP, INS_KEY, REDIS} from "./configs/config";
import SocketListen from './socket/listen';
import HttpListen from './http/listen';
import InsUtils from "./utils/ins-utils";
import JobUtils from "./jobs/job-utils";
import LogUtils from "./utils/log-utils";

import express from "express";
import {Server} from "socket.io";
import {createAdapter} from "@socket.io/redis-adapter";
import Redis from "ioredis";

const insUtils = new InsUtils();
const app = express();
const router = express.Router();

declare global {
    namespace NodeJS {
        interface Global {
            logUtils: LogUtils,
        }
    }
}

/**
 * 监听http
 */
function listenHttp() {
    const log = global.logUtils.createContext('Main', 'listenHttp');
    log.info(`开始初始化Http服务...`);
    // 设置跨域访问
    app.all('*', (req, res, next) => {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
        res.header("X-Powered-By", ' 3.2.1');
        res.header("Content-Type", "application/json;charset=utf-8");
        next();
    });

    // 将请求交给路由
    app.use("/", router);
    log.info("开始初始化http路由...");
    new HttpListen(router);

    // 监听
    app.listen(APP.HTTP_PORT, () => {
        log.info(`http服务监听端口[${APP.HTTP_PORT}]...`);
    });
}

/**
 * 监听socket
 */
function listenSocket() {
    const log = global.logUtils.createContext('Main', 'listenSocket');
    try {
        log.info(`开始初始化Socket服务...`);
        const io = new Server({
            path: '/',
            // 在此时间内客户端没有一个pong包回来，就认为连接已经关闭了
            pingTimeout: 5000,
            // 服务器发送心跳包的间隔时间
            // pingInterval: 60000,
            // 是否启用cookie
            cookie: false,
            maxHttpBufferSize: 2e6
        });
        // 设置请求路径
        io.path('five-chess');

        // 创建Redis实例
        const redisClient: Redis = new Redis(REDIS.PORT, REDIS.HOST, {
            db: Number(REDIS.DB_NAME),
            password: String(REDIS.PASSWORD)
        });
        insUtils.setIns(INS_KEY.REDIS_KEY, redisClient);

        // socket适配器绑定
        const redisSubClient = redisClient.duplicate();
        io.adapter(createAdapter(redisClient, redisSubClient));

        io.listen(APP.SOCKET_PORT);
        insUtils.setIns(INS_KEY.IO_KEY, io);

        log.debug(`开始启动监听服务...`);
        insUtils.setIns(INS_KEY.SERVICE_KEY, new SocketListen(io));

        log.debug(`开始启动调度任务...`);
        insUtils.setIns(INS_KEY.JOB_KEY, new JobUtils(io));

        log.info(`socket服务监听端口[${APP.SOCKET_PORT}]...`);
    } catch (e) {
        log.error('程序启动失败', e);
    }
}

/**
 * 日志初始化(全局日志)
 */
function initLogger() {
    const logUtils = new LogUtils();
    // 创建默认traceId
    logUtils.createTraceId();
    // 全局化
    global.logUtils = logUtils;
}

initLogger();
listenSocket();
listenHttp();